<template>
  <div :class="['custom-bar', `${boxAlign}-box`]" :style="{ height: barHeight }">
    <div
      class="bar"
      :style="{ width: barWidthComp, backgroundColor: barBgColor }"
      @mouseenter="handleMouseEnter"
      @mousemove="handleMouseMove"
      @mouseleave="handleMouseLeave"
    >
      <Teleport to="body">
        <div
          v-if="tooltipBoxObj.show"
          :class="['tooltip-box', { 'animation-box': animation }]"
          :style="{
            left: tooltipBoxObj.startX,
            top: tooltipBoxObj.startY,
            transform: `translate(${tooltipBoxObj.x}, ${tooltipBoxObj.y})`
          }"
          ref="tooltipBoxRef"
        >
          <slot> 自定义tooltip </slot>
        </div>
      </Teleport>
    </div>
    <div class="text-box" :style="{ width: textWidth, lineHeight: barHeight }">{{ text }}</div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'

const props = withDefaults(
  defineProps<{
    barWidth: string // 目前只接受 百分比 'xx%'
    barHeight?: string // '20px'
    barBgColor?: string
    boxAlign?: string // flex-start | flex-end
    text?: string
    textWidth?: string // '80px'
    animation?: boolean
  }>(),
  {
    barWidth: '50%',
    barHeight: '20px',
    barBgColor: '#2CB9B9',
    boxAlign: 'flex-start',
    text: '123',
    textWidth: '80px',
    animation: true
  }
)

const barWidthComp = computed(() => {
  return `calc((100% - ${props.textWidth}) * ${parseFloat(props.barWidth) / 100})`
})

const tooltipBoxObj = ref({
  show: false,
  startX: '0',
  startY: '0',
  x: '0',
  y: '0'
})

const handleMouseEnter = (e: MouseEvent) => {
  tooltipBoxObj.value.startX = e.clientX + 'px'
  tooltipBoxObj.value.startY = e.clientY + 'px'

  tooltipBoxObj.value.show = true
}

const fz = 15
const tooltipBoxRef = ref()
const documentObj = {
  width: document.documentElement.clientWidth,
  height: document.documentElement.clientHeight
}
const handleMouseMove = (e: MouseEvent) => {
  const { width, height } = tooltipBoxRef.value.getBoundingClientRect()

  // x 方向移动
  let moveX = 0
  const x = e.clientX - parseFloat(tooltipBoxObj.value.startX)
  if (documentObj.width - e.clientX < width) {
    moveX = x - fz - width
  } else {
    moveX = x + fz
  }
  tooltipBoxObj.value.x = moveX + 'px'

  // y 方向移动
  let moveY = 0
  const y = e.clientY - parseFloat(tooltipBoxObj.value.startY)
  if (documentObj.height - e.clientY < height) {
    moveY = y - fz - height
  } else {
    moveY = y + fz
  }
  tooltipBoxObj.value.y = moveY + 'px'
}

const handleMouseLeave = () => {
  tooltipBoxObj.value.show = false
}
</script>

<style scoped lang="scss">
.custom-bar {
  display: flex;
  align-items: center;
  flex-wrap: nowrap;
  justify-content: flex-end;
  font-size: 12px;
  gap: 3px;

  .bar {
    width: 100%;
    height: 100%;
  }
  .text-box {
    order: 2;
    height: 100%;
    box-sizing: border-box;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  &.flex-start-box {
    justify-content: flex-start;
    .bar {
      order: 1;
    }
  }
  &.flex-end-box {
    justify-content: flex-end;
    .bar {
      order: 3;
    }
    .text-box {
      text-align: right;
    }
  }
}
</style>

<style lang="scss">
.tooltip-box {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 5;
  &.animation-box {
    transition: all 0.2s;
  }
}
</style>
